package hn.sigit.model.hnd.cadastre;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;

import org.hibernate.annotations.Type;

import hn.sigit.model.ladm.administrative.LA_BAUnit;
import hn.sigit.model.ladm.spatialunit.LA_RequiredRelationshipSpatialUnit;
import hn.sigit.model.ladm.spatialunit.LA_SpatialUnit;
import hn.sigit.model.ladm.spatialunit.LA_SpatialUnitGroup;
import hn.sigit.model.ladm.spatialunit.surveyingandrepresentation.LA_BoundaryFace;
import hn.sigit.model.ladm.spatialunit.surveyingandrepresentation.LA_BoundaryFaceString;
import hn.sigit.model.ladm.spatialunit.surveyingandrepresentation.LA_SpatialSource;
import hn.sigit.util.ParcelComparable;

import com.vividsolutions.jts.geom.Polygon;

@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="HND_Parcel", schema="hnd_cadastre")
@Inheritance(strategy=InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name="LA_SpatialUnitID", referencedColumnName="ID")
public class HND_Parcel extends LA_SpatialUnit implements Serializable, Cloneable, ParcelComparable {
	private static final long serialVersionUID = 1L;

	public HND_Parcel() {
	}
	
	private Polygon shape;
	private Long fieldTab;
	private String cadastralKey;
	private String municipalKey;
	
	private BigDecimal geometryArea;
	private BigDecimal documentedArea;
	private BigDecimal measuredArea;
	private BigDecimal documentedBuiltArea;
	private BigDecimal groundBuiltArea;
	private String parcelName;
	private String neighborhood;
	private String accessWay1;
	private String accessWay2;
	private String houseNumber;
	private String locationInCountry;
	
	private BigDecimal commercialAppraisal;
	private BigDecimal fiscalAppraisal;
	private BigDecimal payedTaxes;
	private HND_TaxStatusType status;
	
	
	@Column(name="Shape", nullable=false)
	@Type(type = "org.hibernatespatial.GeometryUserType")
	public Polygon getShape() {
		return shape;
	}
	public void setShape(Polygon value) {
		this.shape = value;
	}

	@Column(name="FieldTab", nullable=true)
	public Long getFieldTab() {
		return fieldTab;
	}
	public void setFieldTab(Long fieldTab) {
		this.fieldTab = fieldTab;
	}
	
	@Column(name="CadastralKey", nullable=true)
	public String getCadastralKey() {
		return cadastralKey;
	}
	public void setCadastralKey(String cadastralKey) {
		this.cadastralKey = cadastralKey;
	}
	
	@Column(name="MunicipalKey", nullable=true)
	public String getMunicipalKey() {
		return municipalKey;
	}
	public void setMunicipalKey(String municipalKey) {
		this.municipalKey = municipalKey;
	}
	
	@Column(name="GeometryArea", nullable=true, precision=16, scale=8)
	public BigDecimal getGeometryArea() {
		return geometryArea;
	}
	public void setGeometryArea(BigDecimal geometryArea) {
		this.geometryArea = geometryArea;
	}
	
	@Column(name="DocumentedArea", nullable=true, precision=16, scale=8)
	public BigDecimal getDocumentedArea() {
		return documentedArea;
	}
	public void setDocumentedArea(BigDecimal documentedArea) {
		this.documentedArea = documentedArea;
	}
	
	@Column(name="MeasuredArea", nullable=true, precision=16, scale=8)
	public BigDecimal getMeasuredArea() {
		return measuredArea;
	}
	public void setMeasuredArea(BigDecimal measuredArea) {
		this.measuredArea = measuredArea;
	}
	
	@Column(name="DocumentedBuiltArea", nullable=true, precision=16, scale=8)
	public BigDecimal getDocumentedBuiltArea() {
		return documentedBuiltArea;
	}
	public void setDocumentedBuiltArea(BigDecimal documentedBuiltArea) {
		this.documentedBuiltArea = documentedBuiltArea;
	}
	
	@Column(name="GroundBuiltArea", nullable=true, precision=16, scale=8)
	public BigDecimal getGroundBuiltArea() {
		return groundBuiltArea;
	}
	public void setGroundBuiltArea(BigDecimal groundBuiltArea) {
		this.groundBuiltArea = groundBuiltArea;
	}
	
	@Column(name="ParcelName", nullable=true)
	public String getParcelName() {
		return parcelName;
	}
	public void setParcelName(String parcelName) {
		this.parcelName = parcelName;
	}
	
	@Column(name="Neighborhood", nullable=true)
	public String getNeighborhood() {
		return neighborhood;
	}
	public void setNeighborhood(String neighborhood) {
		this.neighborhood = neighborhood;
	}
	
	@Column(name="AccessWay1", nullable=true)
	public String getAccessWay1() {
		return accessWay1;
	}
	public void setAccessWay1(String accessWay1) {
		this.accessWay1 = accessWay1;
	}
	
	@Column(name="AccessWay2", nullable=true)
	public String getAccessWay2() {
		return accessWay2;
	}
	public void setAccessWay2(String accessWay2) {
		this.accessWay2 = accessWay2;
	}
	
	@Column(name="HouseNumber", nullable=true)
	public String getHouseNumber() {
		return houseNumber;
	}
	public void setHouseNumber(String houseNumber) {
		this.houseNumber = houseNumber;
	}
	
	@Column(name="LocationInCountry", nullable=true)
	public String getLocationInCountry() {
		return locationInCountry;
	}
	public void setLocationInCountry(String locationInCountry) {
		this.locationInCountry = locationInCountry;
	}
	
	@Column(name="CommercialAppraisal", nullable=true, precision=16, scale=8)
	public BigDecimal getCommercialAppraisal() {
		return commercialAppraisal;
	}
	public void setCommercialAppraisal(BigDecimal commercialAppraisal) {
		this.commercialAppraisal = commercialAppraisal;
	}
	
	@Column(name="FiscalAppraisal", nullable=true, precision=16, scale=8)
	public BigDecimal getFiscalAppraisal() {
		return fiscalAppraisal;
	}
	public void setFiscalAppraisal(BigDecimal fiscalAppraisal) {
		this.fiscalAppraisal = fiscalAppraisal;
	}
	
	@Column(name="PayedTaxes", nullable=true, precision=16, scale=8)
	public BigDecimal getPayedTaxes() {
		return payedTaxes;
	}
	public void setPayedTaxes(BigDecimal payedTaxes) {
		this.payedTaxes = payedTaxes;
	}
	
	@Column(name="Status", nullable=true)
	@Enumerated(EnumType.STRING)
	public HND_TaxStatusType getStatus() {
		return status;
	}
	public void setStatus(HND_TaxStatusType status) {
		this.status = status;
	}
	
	
	@Transient
	public HND_Property getProperty() {
		HND_Property hndProp = null;
		
		Set<LA_BAUnit> baUnitSet = super.getBaunits();
		for (LA_BAUnit baUnit : baUnitSet) {
			if (baUnit instanceof HND_Property) {
				hndProp = (HND_Property) baUnit;
				break;
			}
		}
		
		return hndProp;
	}
	
	public String toString() {
		return super.toString();
	}
	
	@Override
	public HND_Parcel clone() throws CloneNotSupportedException {
		HND_Parcel clonedHndParcel = (HND_Parcel) super.clone();
		
		//this is in order to mark the object as unsaved
		clonedHndParcel.setSuID(0);
		
		Set<LA_BAUnit> baunits = new HashSet<LA_BAUnit>(getBaunits());
		Set<LA_SpatialUnit> element = new HashSet<LA_SpatialUnit>(getElement());
		Set<LA_SpatialUnitGroup> whole = new HashSet<LA_SpatialUnitGroup>(getWhole());
		Set<LA_SpatialSource> spatialSources = new HashSet<LA_SpatialSource>(getSpatialSources());
		Set<LA_RequiredRelationshipSpatialUnit> relSpatialUnits1La_requiredrelationshipspatialunits = new HashSet<LA_RequiredRelationshipSpatialUnit>(getRelSpatialUnits1La_requiredrelationshipspatialunits());
		Set<LA_RequiredRelationshipSpatialUnit> relSpatialUnits2La_requiredrelationshipspatialunits = new HashSet<LA_RequiredRelationshipSpatialUnit>(getRelSpatialUnits2La_requiredrelationshipspatialunits());
		Set<LA_BoundaryFaceString> bfsMinus = new HashSet<LA_BoundaryFaceString>(getBfsMinus());
		Set<LA_BoundaryFaceString> bfsPlus = new HashSet<LA_BoundaryFaceString>(getBfsPlus());
		Set<LA_BoundaryFace> bfMinus = new HashSet<LA_BoundaryFace>(getBfMinus());
		Set<LA_BoundaryFace> bfPlus = new HashSet<LA_BoundaryFace>(getBfPlus());
		
		clonedHndParcel.setBaunits(baunits);
		clonedHndParcel.setElement(element);
		clonedHndParcel.setWhole(whole);
		clonedHndParcel.setSpatialSources(spatialSources);
		clonedHndParcel.setRelSpatialUnits1La_requiredrelationshipspatialunits(relSpatialUnits1La_requiredrelationshipspatialunits);
		clonedHndParcel.setRelSpatialUnits2La_requiredrelationshipspatialunits(relSpatialUnits2La_requiredrelationshipspatialunits);
		clonedHndParcel.setBfsMinus(bfsMinus);
		clonedHndParcel.setBfsPlus(bfsPlus);
		clonedHndParcel.setBfMinus(bfMinus);
		clonedHndParcel.setBfPlus(bfPlus);
		
		clonedHndParcel.setShape((Polygon)shape.clone());

		return clonedHndParcel;
	}
}
